use std::{fs::File, io::Read};
use std::path::Path;

use mongodb::bson::{Bson, doc};
use serde::{Deserialize, Serialize};

/// 后端接口配置内容
#[derive(Deserialize, Serialize, Debug)]
struct Service {
    port: Option<i32>,     //后端服务启动的端口
    mongo: Option<String>, //mongo服务器的地址
}

/// 服务端日志目录配置
#[derive(Deserialize, Serialize, Debug)]
struct ServiceLog {
    code: Option<String>,  //业务模块标识
    title: Option<String>, //标题
    dir: Option<String>,   //日志目录
}

#[derive(Deserialize, Serialize, Debug)]
pub struct Config {
    service: Service,
    service_log: Option<Vec<ServiceLog>>,
}

pub fn init_config() -> Config {
    Config::load()
}

impl Config {
    /// 从文件中加载配置内容
    pub fn load() -> Config {
        let yml_path = Path::new("config.yml");
        let toml_path = Path::new("config.toml");

        let config: Config;
        //优先读取toml配置文件 yml很多工程配不清楚
        if toml_path.exists() {
            config = Self::load_toml(toml_path);
        }else {
            config = Self::load_yml(yml_path);
        }

        return config;
    }

    fn load_yml(yml_path: &Path) -> Config {

        let mut file = match File::open(yml_path) {
            Ok(f) => f,
            Err(e) => panic!("no such file {} exception:{}", yml_path.display(), e),
        };
        let mut str_val = String::new();
        match file.read_to_string(&mut str_val) {
            Ok(s) => s,
            Err(e) => panic!("Error Reading file: {}", e),
        };

        let config = serde_yaml::from_str(&str_val).unwrap();
        config
    }

    fn load_toml(toml_path: &Path) -> Config {

        let mut file = match File::open(toml_path) {
            Ok(f) => f,
            Err(e) => panic!("no such file {} exception:{}", toml_path.display(), e),
        };
        let mut str_val = String::new();
        match file.read_to_string(&mut str_val) {
            Ok(s) => s,
            Err(e) => panic!("Error Reading file: {}", e),
        };

        let config = toml::from_str(&str_val).unwrap();
        config
    }

    /// 返回配置的端口如果没有配置默认返回10086
    pub fn port(&self) -> i32 {
        self.service.port.unwrap_or_else(|| 10086)
    }

    pub fn mongo(&self) -> &str {
        match &self.service.mongo {
            Some(mongo) => &mongo,
            None => "mongodb://localhost:27017",
        }
    }

    pub fn get_service_log(&self, k: &String) -> String {
        for service_log in self.service_log.as_ref().unwrap() {
            match &service_log.code {
                Some(code) => {
                    if code == k {
                        return service_log.dir.as_ref().unwrap().clone();
                    }
                }

                None => {}
            }
        }
        String::from("")
    }

    pub fn service_log_list(&self) -> Vec<Bson> {
        let mut log_list_doc: Vec<Bson> = Vec::new();
        for service_log in self.service_log.as_ref().unwrap() {
            log_list_doc.push(Bson::Document(doc! {
                "service_code": service_log.code.as_ref().unwrap().clone(),
                "name": service_log.title.as_ref().unwrap().clone()
            }));
        }
        log_list_doc
    }
}
